//===--- UnsafePointer.swift.gyb ------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%import gyb

% for mutable in (True, False):
%  Self = 'UnsafeMutablePointer' if mutable else 'UnsafePointer'
%  a_Self = 'an `UnsafeMutablePointer`' if mutable else 'an `UnsafePointer`'

/// A raw pointer for accessing data of type `Pointee`.  This type
/// provides no automated memory management, and therefore must
/// be handled with great care to ensure safety.
///
/// Instances must be aligned to `MemoryLayout<Pointee>.alignment`, i.e.
/// `(UnsafePointer<Int8>(self) - nil) % MemoryLayout<Pointee>.alignment == 0`
///
/// The memory referenced by an instance can be in one of the following states:
///
/// - Memory is not allocated (for example, pointer is null, or memory has
///   been deallocated previously).
///
/// - Memory is allocated, but value has not been initialized.
///
/// - Memory is allocated and value is initialized.
@_fixed_layout
public struct ${Self}<Pointee>
  : Strideable, Hashable, _Pointer {

  public typealias Distance = Int

  /// The underlying raw (untyped) pointer.
  public let _rawValue: Builtin.RawPointer

  /// Creates ${a_Self} from a builtin raw pointer.
  @_transparent
  public init(_ _rawValue : Builtin.RawPointer) {
    self._rawValue = _rawValue
  }

  /// Converts from an opaque pointer to a typed pointer.
  @_transparent
  public init(_ from : OpaquePointer) {
    _rawValue = from._rawValue
  }

  /// Converts from an opaque pointer to a typed pointer.
  ///
  /// Returns `nil` if `from` is `nil`.
  @_transparent
  public init?(_ from : OpaquePointer?) {
    guard let unwrapped = from else { return nil }
    self.init(unwrapped)
  }

  /// Creates ${a_Self} with a given pattern of bits.
  ///
  /// Returns `nil` if `bitPattern` is zero.
  @_transparent
  public init?(bitPattern: Int) {
    if bitPattern == 0 { return nil }
    self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
  }

  /// Creates ${a_Self} with a given pattern of bits.
  ///
  /// Returns `nil` if `bitPattern` is zero.
  @_transparent
  public init?(bitPattern: UInt) {
    if bitPattern == 0 { return nil }
    self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
  }

  /// Creates ${a_Self} from another `${Self}`.
  @_transparent
  public init(_ other: ${Self}<Pointee>) {
    self = other
  }

  /// Creates ${a_Self} from another `${Self}`.
  ///
  /// Returns `nil` if `other` is `nil`.
  @_transparent
  public init?(_ other: ${Self}<Pointee>?) {
    guard let unwrapped = other else { return nil }
    self = unwrapped
  }

%  if mutable:
  /// Converts from `UnsafePointer` to `UnsafeMutablePointer` of the same
  /// `Pointee`.
  @_transparent
  public init(mutating other: UnsafePointer<Pointee>) {
    self._rawValue = other._rawValue
  }

  /// Converts from `UnsafePointer` to `UnsafeMutablePointer` of the same
  /// `Pointee`.
  ///
  /// Returns nil if `bitPattern` is zero.
  @_transparent
  public init?(mutating other: UnsafePointer<Pointee>?) {
    guard let unwrapped = other else { return nil }
    self.init(mutating: unwrapped)
  }
% else:
  /// Converts from `UnsafeMutablePointer` to ${a_Self} of the same `Pointee`.
  @_transparent
  public init(_ other: UnsafeMutablePointer<Pointee>) {
    self._rawValue = other._rawValue
  }

  /// Converts from `UnsafeMutablePointer` to ${a_Self} of the same `Pointee`.
  ///
  /// Returns nil if `from` is nil.
  @_transparent
  public init?(_ other: UnsafeMutablePointer<Pointee>?) {
    guard let unwrapped = other else { return nil }
    self.init(unwrapped)
  }
%  end

%  if mutable:
  /// Allocates and points at uninitialized aligned memory for `count`
  /// instances of `Pointee`.
  ///
  /// - Postcondition: The pointee is allocated, but not initialized.
  static public func allocate(capacity count: Int)
    -> UnsafeMutablePointer<Pointee> {
    let size = MemoryLayout<Pointee>.stride * count
    let rawPtr =
      Builtin.allocRaw(size._builtinWordValue, Builtin.alignof(Pointee.self))
    Builtin.bindMemory(rawPtr, count._builtinWordValue, Pointee.self)
    return UnsafeMutablePointer(rawPtr)
  }

  /// Deallocates uninitialized memory allocated for `count` instances
  /// of `Pointee`.
  ///
  /// - Precondition: The memory is not initialized.
  ///
  /// - Postcondition: The memory has been deallocated.
  public func deallocate(capacity: Int) {
    let size = MemoryLayout<Pointee>.stride * capacity
    Builtin.deallocRaw(
      _rawValue, size._builtinWordValue, Builtin.alignof(Pointee.self))
  }
%  end

  /// Accesses the `Pointee` instance referenced by `self`.
  ///
  /// - Precondition: Either the pointee has been initialized with an
  ///   instance of type `Pointee`, or `pointee` is being assigned to
  ///   and `Pointee` is a trivial type.
  public var pointee: Pointee {
%  if mutable:
    @_transparent unsafeAddress {
      return UnsafePointer(self)
    }
    @_transparent nonmutating unsafeMutableAddress {
      return self
    }
%  else:
    @_transparent unsafeAddress {
      return self
    }
%  end
  }

%  if mutable:
  /// Initializes `self.pointee` with `count` consecutive copies of `newValue`
  ///
  /// - Precondition: The pointee is not initialized.
  ///
  /// - Precondition: `count` is non-negative.
  ///
  /// - Postcondition: The pointee is initialized; the value should eventually
  ///   be destroyed or moved from to avoid leaks.
  public func initialize(to newValue: Pointee, count: Int = 1) {
    // FIXME: add tests (since the `count` has been added)
    _debugPrecondition(count >= 0,
      "${Self}.initialize(to:): negative count")
    // Must not use `initializeFrom` with a `Collection` as that will introduce
    // a cycle.
    for offset in 0..<count {
      Builtin.initialize(newValue, (self + offset)._rawValue)
    }
  }

  /// Retrieves the `pointee`, returning the referenced memory to an
  /// uninitialized state.
  ///
  /// Equivalent to `{ defer { deinitialize() }; return pointee }()`, but
  /// more efficient.
  ///
  /// - Precondition: The pointee is initialized.
  ///
  /// - Postcondition: The memory is uninitialized.
  public func move() -> Pointee {
    return Builtin.take(_rawValue)
  }

  /// Replaces `count` initialized `Pointee`s starting at `self` with
  /// the `count` `Pointee`s at `source`.
  ///
  /// - Precondition: `count >= 0`
  ///
  /// - Precondition: The `Pointee`s at `source..<source + count` are
  ///   initialized.
  ///
  /// - Precondition: Either the `Pointee`s at `self..<self + count`
  ///   are initialized, or `Pointee` is a trivial type.
  public func assign(from source: UnsafePointer<Pointee>, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.assign with negative count")
    if UnsafePointer(self) < source || UnsafePointer(self) >= source + count {
      // assign forward from a disjoint or following overlapping range.
      for i in 0..<count {
        self[i] = source[i]
      }
    }
    else {
      // assign backward from a non-following overlapping range.
      var i = count-1
      while i >= 0 {
        self[i] = source[i]
        i -= 1
      }
    }
  }

  /// Initializes memory starting at `self` with `count` `Pointee`s
  /// beginning at `source`, and returning the source memory to an
  /// uninitialized state.
  ///
  /// - Precondition: `count >= 0`
  ///
  /// - Precondition: The memory at `self..<self + count` is uninitialized
  ///   and the `Pointees` at `source..<source + count` are
  ///   initialized.
  ///
  /// - Postcondition: The `Pointee`s at `self..<self + count` are
  ///   initialized and the memory at `source..<source + count` is
  ///   uninitialized.
  public func moveInitialize(from source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.moveInitialize with negative count")
    if self < source || self >= source + count {
      // initialize forward from a disjoint or following overlapping range.
      Builtin.takeArrayFrontToBack(
        Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
      // This builtin is equivalent to:
      // for i in 0..<count {
      //   (self + i).initialize(to: (source + i).move())
      // }
    }
    else {
      // initialize backward from a non-following overlapping range.
      Builtin.takeArrayBackToFront(
        Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
      // This builtin is equivalent to:
      // var src = source + count
      // var dst = self + count
      // while dst != self {
      //   (--dst).initialize(to: (--src).move())
      // }
    }
  }

  /// Initializes memory starting at `self` with `count` `Pointee`s
  /// beginning at `source`.
  ///
  /// - Precondition: `count >= 0`
  ///
  /// - Precondition: The memory regions `source..<source + count`
  ///   and `self..<self + count` do not overlap.
  ///
  /// - Precondition: The memory at `self..<self + count` is uninitialized
  ///   and the `Pointees` at `source..<source + count` are
  ///   initialized.
  ///
  /// - Postcondition: The `Pointee`s at `self..<self + count` and
  ///   `source..<source + count` are initialized.
  public func initialize(from source: UnsafePointer<Pointee>, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.initialize with negative count")
    _debugPrecondition(
      UnsafePointer(self) + count <= source ||
      source + count <= UnsafePointer(self),
      "${Self}.initialize overlapping range")
    Builtin.copyArray(
      Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // This builtin is equivalent to:
    // for i in 0..<count {
    //   (self + i).initialize(to: source[i])
    // }
  }

  /// Initializes memory starting at `self` with the elements of `source`.
  ///
  /// - Precondition: The memory at `self..<self + count` is
  ///   uninitialized.
  ///
  /// - Postcondition: The `Pointee`s at `self..<self + count` are
  ///   initialized.
  public func initialize<C : Collection>(from source: C)
    where C.Iterator.Element == Pointee {
    source._copyContents(initializing: self)
  }

  /// Replaces `count` initialized `Pointee`s starting at `self` with
  /// the `count` `Pointee`s starting at `source`, returning the
  /// source memory to an uninitialized state.
  ///
  /// - Precondition: `count >= 0`
  ///
  /// - Precondition: The memory regions `source..<source + count`
  ///   and `self..<self + count` do not overlap.
  ///
  /// - Precondition: The `Pointee`s at `self..<self + count` and
  ///   `source..<source + count` are initialized.
  ///
  /// - Postcondition: The `Pointee`s at `self..<self + count` are
  ///   initialized and the `Pointees` at `source..<source + count`
  ///   are uninitialized.
  public func moveAssign(from source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.moveAssign(from:) with negative count")
    _debugPrecondition(
      self + count <= source || source + count <= self,
      "moveAssign overlapping range")
    Builtin.destroyArray(Pointee.self, self._rawValue, count._builtinWordValue)
    Builtin.takeArrayFrontToBack(
      Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // These builtins are equivalent to:
    // for i in 0..<count {
    //   self[i] = (source + i).move()
    // }
  }

  /// De-initializes the `count` `Pointee`s starting at `self`, returning
  /// their memory to an uninitialized state.
  ///
  /// Returns an UnsafeMutableRawPointer to this memory.
  ///
  /// - Precondition: The `Pointee`s at `self..<self + count` are
  ///   initialized.
  ///
  /// - Postcondition: The memory is uninitialized.
  @discardableResult
  public func deinitialize(count: Int = 1) -> UnsafeMutableRawPointer {
    _debugPrecondition(count >= 0, "${Self}.deinitialize with negative count")
    // FIXME: optimization should be implemented, where if the `count` value
    // is 1, the `Builtin.destroy(Pointee.self, _rawValue)` gets called.
    Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue)
    return UnsafeMutableRawPointer(self)
  }
%  end

  /// Rebinds memory at `self` to type `T` with capacity to hold `count`
  /// adjacent `T` values while executing the `body` closure.
  ///
  /// After executing the closure, rebinds memory back to `Pointee`.
  ///
  /// - Precondition: Type 'T' is layout compatible with type 'Pointee'.
  /// - Precondition: The memory `self..<self + count * MemoryLayout<T>.stride`
  ///   is bound to `Pointee`.
  ///
  /// Accessing `${Self}<T>.pointee` requires that the memory be "bound" to
  /// type `T`.  A memory location may only be bound to one type at a time, so
  /// accessing the same memory as an unrelated type without first rebinding the
  /// memory is undefined. `self` may not be accessed within the `body` closure
  /// because memory is no longer bound to `Pointee` while it executes. The
  /// closure's `${Self}<T>` argument must not escape the closure because memory
  /// is only temporarily bound to `T`.
  ///
  /// To persistently bind this memory to a different type, first obtain a
  /// raw pointer to the memory, then invoke the `bindMemory` API:
  /// `UnsafeRawPointer(typedPointer).bindMemory(to:capacity:)`.
  public func withMemoryRebound<T, Result>(to: T.Type, capacity count: Int,
    _ body: (${Self}<T>) throws -> Result
  ) rethrows -> Result {
    Builtin.bindMemory(_rawValue, count._builtinWordValue, T.self)
    defer {
      Builtin.bindMemory(_rawValue, count._builtinWordValue, Pointee.self)
    }
    return try body(${Self}<T>(_rawValue))
  }

  /// Accesses the pointee at `self + i`.
  ///
  /// - Precondition: Either the pointee at `self + i` is initialized, or the
  ///   subscript is the left side of an assignment and `Pointee` is a trivial
  ///   type.
  public subscript(i: Int) -> Pointee {
%  if mutable:
    @_transparent
    unsafeAddress {
      return UnsafePointer(self + i)
    }
    @_transparent
    nonmutating unsafeMutableAddress {
      return self + i
    }
%  else:
    @_transparent
    unsafeAddress {
      return self + i
    }
%  end
  }

  //
  // Protocol conformance
  //

  /// The pointer's hash value.
  ///
  /// The hash value is not guaranteed to be stable across different
  /// invocations of the same program.  Do not persist the hash value across
  /// program runs.
  public var hashValue: Int {
    return Int(bitPattern: self)
  }

  /// Returns the next consecutive position.
  public func successor() -> ${Self} {
    return self + 1
  }

  /// Returns the previous consecutive position.
  public func predecessor() -> ${Self} {
    return self - 1
  }

  /// Returns `end - self`.
  public func distance(to x: ${Self}) -> Int {
    return x - self
  }

  /// Returns `self + n`.
  public func advanced(by n: Int) -> ${Self} {
    return self + n
  }
}

extension ${Self} : CustomDebugStringConvertible {
  /// A textual representation of the pointer, suitable for debugging.
  public var debugDescription: String {
    return _rawPointerToString(_rawValue)
  }
}

extension ${Self} : CustomReflectable {
  public var customMirror: Mirror {
    let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
    return Mirror(self, children: ["pointerValue": ptrValue])
  }
}

extension ${Self} : CustomPlaygroundQuickLookable {
  var summary: String {
    let selfType = "${Self}"
    let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
    return ptrValue == 0 ? "\(selfType)(nil)" : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
  }

  public var customPlaygroundQuickLook: PlaygroundQuickLook {
    return .text(summary)
  }
}

/// - Note: Strideable's implementation is potentially less efficient and cannot
///   handle misaligned pointers.
@_transparent
public func == <Pointee>(
  lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>
) -> Bool {
  return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
}

/// - Note: Strideable's implementation is potentially less efficient and cannot
///   handle misaligned pointers.
///
/// - Note: This is an unsigned comparison unlike Strideable's implementation.
@_transparent
public func < <Pointee>(lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
  return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
}

/// - Note: The following family of operator overloads are redundant
///   with Strideable. However, optimizer improvements are needed
///   before they can be removed without affecting performance.
@_transparent
public func + <Pointee>(lhs: ${Self}<Pointee>, rhs: Int) -> ${Self}<Pointee> {
  return ${Self}(Builtin.gep_Word(
    lhs._rawValue, rhs._builtinWordValue, Pointee.self))
}

@_transparent
public func + <Pointee>(lhs: Int,
           rhs: ${Self}<Pointee>) -> ${Self}<Pointee> {
  return rhs + lhs
}

@_transparent
public func - <Pointee>(lhs: ${Self}<Pointee>, rhs: Int) -> ${Self}<Pointee> {
  return lhs + -rhs
}

@_transparent
public func - <Pointee>(lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Int {
  return
    Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs._rawValue),
                         Builtin.ptrtoint_Word(rhs._rawValue)))
    / MemoryLayout<Pointee>.stride
}

@_transparent
public func += <Pointee>(lhs: inout ${Self}<Pointee>, rhs: Int) {
  lhs = lhs + rhs
}

@_transparent
public func -= <Pointee>(lhs: inout ${Self}<Pointee>, rhs: Int) {
  lhs = lhs - rhs
}

extension ${Self} {
  @available(*, unavailable, message:
    "use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
  public init<U>(_ from : UnsafeMutablePointer<U>) { Builtin.unreachable() }

  @available(*, unavailable, message:
    "use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
  public init?<U>(_ from : UnsafeMutablePointer<U>?) { Builtin.unreachable(); return nil }

  @available(*, unavailable, message:
    "use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
  public init<U>(_ from : UnsafePointer<U>) { Builtin.unreachable() }

  @available(*, unavailable, message:
    "use 'withMemoryRebound(to:capacity:_)' to temporarily view memory as another layout-compatible type.")
  public init?<U>(_ from : UnsafePointer<U>?) { Builtin.unreachable(); return nil }

 % if mutable:
  @available(*, unavailable, renamed: "init(mutating:)")
  public init(_ from : UnsafePointer<Pointee>) { Builtin.unreachable() }

  @available(*, unavailable, renamed: "init(mutating:)")
  public init?(_ from : UnsafePointer<Pointee>?) { Builtin.unreachable(); return nil }
% end

  @available(*, unavailable, renamed: "Pointee")
  public typealias Memory = Pointee

  @available(*, unavailable, message: "use 'nil' literal")
  public init() {
    Builtin.unreachable()
  }

% if mutable:
  @available(*, unavailable, renamed: "allocate(capacity:)")
  public static func alloc(_ num: Int) -> ${Self} {
    Builtin.unreachable()
  }

  @available(*, unavailable, message: "use '${Self}.allocate(capacity:)'")
  public init(allocatingCapacity: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "deallocate(capacity:)")
  public func dealloc(_ num: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "deallocate(capacity:)")
  public func deallocateCapacity(_ num: Int) {
    Builtin.unreachable()
  }
% end

  @available(*, unavailable, renamed: "pointee")
  public var memory: Pointee {
    get {
      Builtin.unreachable()
    }
% if mutable:
    set {
      Builtin.unreachable()
    }
% end
  }

% if mutable:
  @available(*, unavailable, renamed: "initialize(to:)")
  public func initialize(_ newvalue: Pointee) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "initialize(to:count:)")
  public func initialize(with newvalue: Pointee, count: Int = 1) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "deinitialize(count:)")
  public func destroy() {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "deinitialize(count:)")
  public func destroy(_ count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "initialize(from:)")
  public func initializeFrom<C : Collection>(_ source: C) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "initialize(from:count:)")
  public func initializeFrom(_ source: UnsafePointer<Pointee>, count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "assign(from:count:)")
  public func assignFrom(_ source: UnsafePointer<Pointee>, count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "assign(from:count:)")
  public func assignBackwardFrom(_ source: UnsafePointer<Pointee>, count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "moveInitialize(from:count:)")
  public func moveInitializeFrom(_ source: UnsafePointer<Pointee>, count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "moveInitialize(from:count:)")
  public func moveInitializeBackwardFrom(_ source: UnsafePointer<Pointee>,
    count: Int) {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "moveAssign(from:count:)")
  public func moveAssignFrom(_ source: UnsafePointer<Pointee>, count: Int) {
    Builtin.unreachable()
  }
% end
}

extension Int {
  public init<U>(bitPattern: ${Self}<U>?) {
    if let bitPattern = bitPattern {
      self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
    } else {
      self = 0
    }
  }
}

extension UInt {
  public init<U>(bitPattern: ${Self}<U>?) {
    if let bitPattern = bitPattern {
      self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
    } else {
      self = 0
    }
  }
}
% end # for mutable

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
